package com.gitee.l0km.casban;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import com.gitee.l0km.aocache.Singleton;
import com.gitee.l0km.aocache.annotations.AoWeakCacheable;
import com.gitee.l0km.casban.annotations.AnnotationFieldNames;
import com.gitee.l0km.casban.annotations.CasbanScan;
import com.gitee.l0km.casban.annotations.ConstantComponent;
import com.gitee.l0km.casban.annotations.CasbanComponent;
import com.gitee.l0km.casban.annotations.ConstantSupplier;
import com.gitee.l0km.casban.annotations.ScanConfig;
import com.gitee.l0km.casban.exception.PackageScanException;
import com.gitee.l0km.casban.utils.CollectionUtils;
import com.gitee.l0km.com4j.base.ConditionChecks;
import com.gitee.l0km.com4j.base.ILazyInitVariable;
import com.gitee.l0km.com4j.base.SPIUtils;
import com.gitee.l0km.com4j.base.ILazyInitVariable.VolatileReferenceVar;
import com.gitee.l0km.common.spring.core.annotation.AnnotatedElementUtils;
import com.gitee.l0km.common.spring.core.annotation.AnnotationAttributes;
import com.gitee.l0km.common.spring.core.annotation.AnnotationUtils;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.gitee.l0km.casban.PackageScanners.PACKAGE_SCANNER;
import static com.gitee.l0km.com4j.base.SimpleLog.log;
import static com.gitee.l0km.com4j.base.SimpleLog.logString;
import static com.google.common.base.Preconditions.checkArgument;

/**
 * 用于扫描和缓存带有特定注解的类，支持动态加载和缓存管理。
 * <p>
 * 该类主要用于扫描带有@CasbanScan、@CasbanComponent等注解的类，
 * 并提供缓存功能以提高性能。
 * <p>
 * 使用示例：
 * <pre>
 * // 获取扫描器实例
 * CasbanCachedClassScanner scanner = CasbanCachedClassScanner.getInstance();
 * // 设置调试输出
 * scanner.setDebugOutput(true);
 * </pre>
 * <p>
 * 注意事项：
 * <ul>
 * <li>该类是线程安全的，使用ReentrantReadWriteLock保证并发访问安全</li>
 * <li>扫描结果会被缓存，避免重复扫描相同包</li>
 * <li>可以通过SPI机制扩展扫描行为</li>
 * </ul>
 * 
 * @author guyadong
 */
public class CasbanCachedClassScanner implements AnnotationFieldNames{
	/**
	 * 扫描范围: 扫描的顶级包名
	 */
	private final static Map<String, CasbanScan> casbanScanAnnots;

	private final LinkedHashSet<Class<?>> classes = new LinkedHashSet<>();
	private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
	/** 已扫描的包名 */
	private final LinkedHashSet<String> scannedPackages = new LinkedHashSet<>();
	protected boolean debugOutput = true;

	private volatile static CasbanCachedClassScanner instance;
	protected CasbanCachedClassScanner() {
		scan0(casbanScanAnnots.values());
	}
	static {
		/** SPI方法从 CasbanScan 实例获取扫描包名 */
		ServiceLoader<CasbanBoot> serviceLoader= SPIUtils.serviceLoaderOf(CasbanBoot.class);
		final LinkedHashSet<CasbanScan> _casbanScanAnnots = new LinkedHashSet<>();
		for(CasbanBoot casbanBoot:serviceLoader) {
			log("CasbanScan:{}", casbanBoot.getClass().getName());
			Set<CasbanScan> annots = AnnotatedElementUtils.findAllMergedAnnotations(
					casbanBoot.getClass(), CasbanScan.class);
			for(CasbanScan annot:annots) {
				CasbanScan rebuilt = rebuild(annot);
				_casbanScanAnnots.add(rebuilt);
			}
		}
		LinkedHashSet<CasbanScan> mergedAnnots = mergeExcludedCasbanScans(_casbanScanAnnots);
		casbanScanAnnots = rebuild(mergedAnnots);
	}
	public static CasbanCachedClassScanner getInstance() {
		if(null == instance) {
			synchronized (CasbanCachedClassScanner.class) {
				if(null == instance) {
					instance = new CasbanCachedClassScanner();
				}
			}
		}
		return instance;
	}
	protected static void setInstance(CasbanCachedClassScanner instance) {
		if(null != instance) {
			CasbanCachedClassScanner.instance = instance;
		}
	}
	@AoWeakCacheable(maximumSize = 200, expireAfterAccess = 20, expireAfterAccessTimeUnit = TimeUnit.SECONDS)
	private static Predicate<String> excludedPackageFilterOf(CasbanScan annot){
		return Predicates.or(
				CommonPredicates.basePackageFilter(annot.excludePackages()),
				CommonPredicates.endsWithFilter(annot.excludePackageTails()));
	}
	private static final Function<String, CasbanScan> CASBAN_FUN = new Function<String, CasbanScan>() {
		@Override
		public CasbanScan apply(String packagename) {
			ImmutableMap<String, Object> attrs = ImmutableMap.<String,Object>of(
					BASE_PACKAGES,new String[] {checkNotNull(packagename,"packagename is null")});
			return AnnotationUtils.synthesizeAnnotation(attrs,CasbanScan.class,null);
		}
	};

	protected Set<Class<?>> getClasses() {
		/** 将给定的类集合转换为不可变集合，以有利于后续aocache缓存正确匹配KEY< */
		return CollectionUtils.asImmutableSet(classes);
	}
	public CasbanCachedClassScanner setDebugOutput(boolean debugOutput) {
		this.debugOutput = debugOutput;
		return this;
	}
	/**
	 * 读取{@link CasbanScan}字段值保存到{@code basePackages,excludedPackages,excludedPackageTails}中
	 * @param annot
	 * @param basePackages
	 * @param excludedPackages
	 * @param excludedPackageTails
	 */
	private static void extract(CasbanScan annot,
			Set<String> basePackages,	Set<String> excludedPackages, Set<String> excludedPackageTails) {
		AnnotationAttributes attrs= AnnotationUtils.getAnnotationAttributes(null, annot);
		basePackages.addAll(Arrays.asList( attrs.getStringArray(BASE_PACKAGES)));
		excludedPackages.addAll(Arrays.asList( attrs.getStringArray(EXCLUDED_PACKAGES)));
		excludedPackageTails.addAll(Arrays.asList( attrs.getStringArray(EXCLUDED_PACKAGE_TAILS)));
		basePackages.addAll(asPackagenames(attrs.getClassArray(BASE_PACKAGES_CLASSES)));
		excludedPackages.addAll(asPackagenames(attrs.getClassArray(EXCLUDED_PACKAGES_CLASSES)));
	}
	/**
	 * 对{@code basePackages,excludedPackages,excludedPackageTails}进行归一化处理<br>
	 * 
	 * @param basePackages
	 * @param excludedPackages
	 * @param excludedPackageTails
	 * @param excludeSubpackage 为{@code true}则{@code excludedPackages}只保留 basePackages中的子包名
	 */
	private static void merge(	Set<String> basePackages,	Set<String> excludedPackages, Set<String> excludedPackageTails, boolean excludeSubpackage) {
		LinkedHashSet<String> _basePackages = mergePackages(basePackages);
		
		/** excludePackages和basePackages存在相同包名，以basePackages优先，
		 * 从excludePackages 删除与 basePackages 冲突的包名 */
		excludedPackages.removeAll(_basePackages);
		LinkedHashSet<String>_excludedPackages;
		if(excludeSubpackage) {
			/** excludePackages 只保留 basePackages中的子包名  */
			_excludedPackages = FluentIterable.from(excludedPackages)
					.filter(CommonPredicates.basePackageFilter(basePackages))
					.copyInto(new LinkedHashSet<String>());
		}
		/** 忽略excludePackages 中 为basePackages中的父级的包名  */
		_excludedPackages = FluentIterable.from(excludedPackages)
				.filter(Predicates.not(CommonPredicates.basePackageFilter(basePackages,true)))
				.copyInto(new LinkedHashSet<String>());
		_excludedPackages = mergePackages(_excludedPackages);
		/** 如果 excludedPackageTails 与  basePackages 或 excludePackages 中的包名冲突，则忽略  */
		excludedPackageTails.removeAll(basePackages);
		excludedPackageTails.removeAll(excludedPackages);
		basePackages.retainAll(_basePackages);
		excludedPackages.retainAll(_excludedPackages);
	}
	private static CasbanScan build(Iterable<String> basePackages,
			Iterable<String> excludedPackages,Iterable<String> excludedPackageTails) {
		Map<String, Object> attrs = new LinkedHashMap<>();
		FluentIterable.from(basePackages).toArray(String.class);
		attrs.put(BASE_PACKAGES, FluentIterable.from(basePackages).toArray(String.class));
		attrs.put(EXCLUDED_PACKAGES, FluentIterable.from(excludedPackages).toArray(String.class));
		attrs.put(EXCLUDED_PACKAGE_TAILS, FluentIterable.from(excludedPackageTails).toArray(String.class));
		return AnnotationUtils.synthesizeAnnotation(attrs, CasbanScan.class, null);
	}
	static CasbanScan rebuild(CasbanScan annot) {
		LinkedHashSet<String> basePackages = new LinkedHashSet<>();
		LinkedHashSet<String> excludedPackages = new LinkedHashSet<>();
		LinkedHashSet<String> excludedPackageTails = new LinkedHashSet<>();
		extract(annot, basePackages,excludedPackages,excludedPackageTails);
		merge(basePackages, excludedPackages, excludedPackageTails, false);
		return build(basePackages, excludedPackages, excludedPackageTails);
	}

	/**
	 * 合并多个{@link CasbanScan}实例，并返回合并后的实例集合，合并后集合的实例数量会等于或少于输入的实例数量<br>
	 * 如果一个{@link CasbanScan}实例的basePackages字段的包名包含在另一个{@link CasbanScan}实例的excludedPackages字段中，则该实例会被合并到另一个实例中
	 * 
	 * @param annots
	 * @return 合并后的实例集合
	 * @see #findExcludeCasbanScan(Iterable, CasbanScan)
	 * @since 1.4.1
	 */
	static LinkedHashSet<CasbanScan> mergeExcludedCasbanScans(Iterable<CasbanScan> annots) {
		List<CasbanScan> mergedAnnots = Lists.newArrayList(Sets.newLinkedHashSet(annots));
		for (int i = 0; i < mergedAnnots.size(); i++) {
			CasbanScan annot = mergedAnnots.get(i);
			CasbanScan excluded = findExcludeCasbanScan(mergedAnnots, annot);
			if (null != excluded) {
				/** 合并 annot 到 excluded，并从 merged 中删除 annot */
				mergedAnnots.remove(i);
				/** 索引减1避免漏掉列表中的元素 */
				i--;
				int excludedIndex = mergedAnnots.indexOf(excluded);
				CasbanScan merged = mergeToExcluded(annot, excluded);
				/** 更新 merged中的 excluded */
				mergedAnnots.set(excludedIndex, merged);
			}
		}
		return new LinkedHashSet<>(mergedAnnots);
	}

	private static CasbanScan mergeToExcluded(CasbanScan annot, CasbanScan excluded) {
		/** 合并 excludedPackages */
		Set<String> excludedPackages = FluentIterable.from(excluded.excludePackages()).append(annot.excludePackages())
				.copyInto(new LinkedHashSet<String>());
		/** 合并 excludedPackageTails */
		Set<String> excludedPackageTails = FluentIterable.from(excluded.excludePackageTails())
				.append(annot.excludePackageTails()).copyInto(new LinkedHashSet<String>());
		/** 合并 annot 到 excluded */
		return build(Arrays.asList(excluded.basePackages()), excludedPackages, excludedPackageTails);
	}

	/**
	 * 在{@code annots}中查找排除(excludedPackages)包名中包含了 {@code annot}
	 * 的基础包名(basePackages)的 {@link CasbanScan} 实例,如果没有找到，则返回 {@code null}<br>
	 * 例如有如下两个注解作为 {@code annots},第一个注解作为 {@code annot}
	 * 
	 * <pre>
	 *  &#64;CasbanScan(basePackages={"you.pkg1"},excludePackages={"you.pkg3"})
	 *  &#64;CasbanScan(basePackages={"you.pkg2"},excludePackages={"you.pkg1"})
	 * </pre>
	 * 
	 * 则 {@code findExcludeCasbanScan(annots,annot)} 返回
	 * {@code @CasbanScan(basePackages={"you.pkg2"},excludePackages={"you.pkg1","you.pkg3"})}<br>
	 * 如果存在相互排除的包名，则抛出异常，例如：
	 * 
	 * <pre>
	 * 	&#64;CasbanScan(basePackages={"you.pkg1"},excludePackages={"you.pkg2"})
	 * 	&#64;CasbanScan(basePackages={"you.pkg2"},excludePackages={"you.pkg1"})
	 * </pre>
	 * 
	 * 注意：如果 {@code annots} 中存在多个匹配的 {@link CasbanScan} 实例，则只会返回第一个匹配的实例
	 * 
	 * @param annots
	 * @param annot
	 * @see #rebuild(CasbanScan)
	 */
	private static CasbanScan findExcludeCasbanScan(Iterable<CasbanScan> annots, CasbanScan annot) {
		for (CasbanScan an : annots) {
			if (Arrays.asList(an.excludePackages()).containsAll(Arrays.asList(annot.basePackages()))) {
//				SimpleLog.log("FIND EXCLUDED: \nexcluded {} \nBY\n {}",annot,an);
				if (Arrays.asList(annot.excludePackageTails()).containsAll(Arrays.asList(an.basePackages()))) {
					/** 相互排除的包名，则抛出异常 */
					throw new PackageScanException(
							"EXCLUDE_PACKAGES CONFLICT:excludePackages of " + annot + " is conflict with " + an);
				}
				return an;
			}
		}
		return null;
	}
	static Map<String, CasbanScan> rebuild(Iterable<CasbanScan> annots) {
		LinkedHashSet<String> basePackages = new LinkedHashSet<>();
		LinkedHashSet<String> excludedPackages = new LinkedHashSet<>();
		LinkedHashSet<String> excludedPackageTails = new LinkedHashSet<>();
		for(CasbanScan annot :annots) {
			extract(annot, basePackages,excludedPackages,excludedPackageTails);
		}
		merge(basePackages,excludedPackages,excludedPackageTails,true);
		LinkedHashMap<String,CasbanScan> synthesizers = new LinkedHashMap<>();
		/** 每一个包名合成一个对应的  @CasbanScan  实例 */
		for(String bp:basePackages) {
			Map<String, Object> map = new HashMap<>();
			map.put(BASE_PACKAGES, new String[] {bp});
			/** excludePackages 只保留 basePackage中的子包名  */
			String[] exp = FluentIterable.from(excludedPackages)
					.filter(CommonPredicates.basePackageFilter(bp))
					.toArray(String.class);
			map.put(EXCLUDED_PACKAGES, exp);
			map.put(EXCLUDED_PACKAGE_TAILS, excludedPackageTails.toArray(new String[0]));
			synthesizers.put(bp,AnnotationUtils.synthesizeAnnotation(map, CasbanScan.class, null));
		}
		return Collections.unmodifiableMap(synthesizers);
	}
	/**
	 * 去除重复包名及子包名以为空或{@code null}的元素
	 * @param packagenames
	 */
	static LinkedHashSet<String> mergePackages(Iterable<String>packagenames) {
		LinkedHashSet<String> topset = Sets.newLinkedHashSet();
		if(null != packagenames) {
			/** 去重及为空或null的元素 */
			LinkedHashSet<String> noempty = FluentIterable.from(packagenames)
					.filter(CommonPredicates.noEmptyFilter())
					.copyInto(new LinkedHashSet<String>());
			for(final String sub:noempty) {
				/** 忽略topset中所有包的子包名 */
				if(!CommonPredicates.basePackageFilter(topset).apply(sub)) {
					ImmutableSet<String> subs = FluentIterable.from(topset).
							filter(CommonPredicates.basePackageFilter(sub)).toSet();
					/** 删除topset中所有当前包名的子包 */
					topset.removeAll(subs);
					/** 将当前包加到topset */
					topset.add(sub);
				}
			}
		}
		return topset;
	}
	/**
	 * 清除所有缓存的类
	 */
	public void clear() {
		readWriteLock.writeLock().lock();
		try {
			scannedPackages.clear();
			classes.clear();
		} finally {
			readWriteLock.writeLock().unlock();
		}
	}
	/**
	 * 将类名转为包名
	 * @param topPackageClasses
	 */
	private static LinkedHashSet<String> asPackagenames(Class<?>...topPackageClasses) {
		LinkedHashSet<String> packagenames = new LinkedHashSet<String>();
		if(null != topPackageClasses) {
			return FluentIterable.from(topPackageClasses)
					.filter(Predicates.notNull())
					.transform(CommonFunctions.basePakageOfClassFun())
					.copyInto(packagenames);
		}
		return packagenames;
	}
	/**
	 * 扫描指定类名所在包下的所有类
	 * @param topPackageClasses
	 * @return 实际扫描的包名数量
	 */
	public int scan(Class<?>...topPackageClasses) {
		checkNotNull(topPackageClasses,"topPackageClasses is null");
		return scan(asPackagenames(topPackageClasses));
	}
	/**
	 * 扫描指定的包名
	 * @param packagenames
	 * @return 实际扫描的包名数量
	 */
	public int scan(String...packagenames) {
		checkNotNull(packagenames,"packagenames is null");
		return scan(FluentIterable.from(packagenames));
	}
	/**
	 * 扫描指定的包名，如果包名为已扫描包名或子包，则忽略
	 * @param packagenames
	 * @return 实际扫描的包名数量
	 */
	public int scan(Iterable<String>packagenames) {
		FluentIterable<CasbanScan> annots = FluentIterable.from(mergePackages(packagenames))
			/** 过滤掉已经扫描过的包名 */
			.filter(Predicates.not(CommonPredicates.startsWithFilter(scannedPackages))).transform(CASBAN_FUN);
		return scan0(annots);
	}
	/**
	 * 扫描指定的包名，如果包名为已扫描包名或子包，则忽略
	 * @param packagenames
	 * @return 实际扫描的包名数量
	 */
	private int scan0(Iterable<CasbanScan>casbanScanAnnots) {
		readWriteLock.writeLock().lock();
		try {
			int count = 0;
			for(CasbanScan annot:casbanScanAnnots) {
				String[] basePackages = annot.basePackages();
				if(basePackages.length>0 && !basePackages[0].isEmpty()) {
					String pkg = basePackages[0];
					Set<Class<?>> loaded = PACKAGE_SCANNER.getClasses(pkg, 
							CountLimitStrategy.ANY, 
							excludedPackageFilterOf(annot));
					classes.addAll(loaded);
					/** 将扫描过的包加入到已经扫描包名集合 */
					scannedPackages.add(pkg);
					count++;
					if(debugOutput) {
						Map<String, Object> map = AnnotationUtils.getAnnotationAttributes(annot);
						map.remove(AnnotationFieldNames.VALUE);
						Map<String, Object> noEmpty = Maps.filterValues(map, CommonPredicates.noEmptyFilter());
						AnnotationAttributes attrs = new AnnotationAttributes(noEmpty);
						log("scan package:{}, {} classes",attrs,loaded.size());
					}
				}
			}
			return count;
		} finally {
			readWriteLock.writeLock().unlock();
		}
	}
	@SafeVarargs
	public final Set<Class<?>> getClasses(Supplier<RangeFilter> finisher, Predicate<Class<?>>... filters){
		readWriteLock.readLock().lock();
		try {
			return CasbanScanners.findClasses(getClasses(), finisher, filters);
		} finally {
			readWriteLock.readLock().unlock();
		}
	}
	public final Set<Class<?>> getClasses(Supplier<RangeFilter> finisher, Iterable<Predicate<Class<?>>>filters){
		readWriteLock.readLock().lock();
		try {
			return CasbanScanners.findClasses(getClasses(), finisher, filters);
		} finally {
			readWriteLock.readLock().unlock();
		}
	}
	@SafeVarargs
	public final Class<?> getClass(boolean onlyOne, Predicate<Class<?>>... filters) {
		checkArgument(null!=filters && filters.length>0,"NOT EMPTY filters required");
		Set<Class<?>> classes = getClasses(CountLimitStrategy.ANY,filters);
		return fetchClassOrnull(classes, onlyOne);
	}
	protected Class<?> fetchClassOrnull(Set<Class<?>> classes,boolean onlyOne){
		return CasbanScanners.fetchClassOrnull(classes, onlyOne, "class");
	}
	public Set<Member> findMembers(
			Supplier<RangeFilter> finisher, 
			Iterable<Predicate<Class<?>>> classFilters,
			Iterable<Predicate<Member>> memberFilters){
		return CasbanScanners.findMembers(getClasses(), finisher, classFilters,memberFilters);
	}
	public Member findMember(boolean onlyOne,
			Iterable<Predicate<Class<?>>> classFilters,
			Iterable<Predicate<Member>> memberFilters){
		return CasbanScanners.findMember(getClasses(),onlyOne,classFilters, memberFilters);
	}
	public Member findConstSupplierMember(Class<?> clazz,
			Iterable<Predicate<Member>> memberFilters,
			boolean onlyOne) {
		LinkedHashSet<Predicate<Member>> _memberFilters = withConstSupplierMemberFilter(memberFilters);
		return CasbanScanners.findMember(clazz, onlyOne, _memberFilters);
	}
	static protected LinkedHashSet<Predicate<Member>> withConstSupplierMemberFilter(Iterable<Predicate<Member>> memberFilters){
		LinkedHashSet<Predicate<Member>> _memberFilters = Sets.newLinkedHashSet(
				Arrays.asList(CommonPredicates.constSupplierMemberFilter()));
		if(null != memberFilters) {
			Iterables.addAll(_memberFilters, memberFilters);
		}
		return _memberFilters;
	}
	static protected LinkedHashSet<Predicate<Class<?>>> withSimpleIClassFilter(Class<?> superClass, Iterable<Predicate<Class<?>>> classFilters){
		LinkedHashSet<Predicate<Class<?>>> _classFilters = Sets.newLinkedHashSet(
				Arrays.asList(
						CommonPredicates.publicClassFilter(), 
						CommonPredicates.noAbstractClassFilter(), 
						CommonPredicates.hasDefaultConstructorFilter()));
		if(null != superClass) {
			_classFilters.add(Predicates.subtypeOf(superClass));
		}
		if(null != classFilters) {
			Iterables.addAll(_classFilters, classFilters);
		}
		return _classFilters;
	}
	
	protected Member findConstSupplierMember(
			Iterable<Predicate<Class<?>>> classFilters,
			Iterable<Predicate<Member>> memberFilters, boolean onlyOne){
		LinkedHashSet<Predicate<Member>> _memberFilters = withConstSupplierMemberFilter(memberFilters);
		return CasbanScanners.findMember(getClasses(),onlyOne,classFilters,_memberFilters);
	}
	protected Member findMember(Iterable<Member> input,	Iterable<Predicate<Member>> memberFilters, boolean onlyOne){
		return CasbanScanners.findMember(input,onlyOne,memberFilters);
	}
	protected Set<Member> findConstSupplierMembers(
			Iterable<Predicate<Class<?>>> classFilters,
			Iterable<Predicate<Member>> memberFilters){
		LinkedHashSet<Predicate<Member>> _memberFilters = withConstSupplierMemberFilter(memberFilters);
		return CasbanScanners.findMembers(getClasses(),CountLimitStrategy.ANY, classFilters,_memberFilters);
	}
	public final <T> T readValue( 
			Iterable<Predicate<Class<?>>> classFilters,
			Iterable<Predicate<Member>> memberFilters) {
		checkArgument(null != classFilters || null != memberFilters,
				"classFilters or memberFilters mut not null");
		Member member = findConstSupplierMember(classFilters, memberFilters, true);
		return readStaticValue(member);
	}
	public final <T> T readValue(T defaultValue,
			Iterable<Predicate<Class<?>>> classFilters,
			Iterable<Predicate<Member>> memberFilters) {
		checkArgument(null != classFilters || null != memberFilters,
				"classFilters or memberFilters mut not null");
		Member member = findConstSupplierMember(classFilters, memberFilters,false);
		if(null == member) {
			return defaultValue;
		}
		T value = readStaticValue(member);
		return null == value ? defaultValue:value;
	}
	public final <T> T readValue(Class<?> clazz, 
			Iterable<Predicate<Member>> memberFilters) {
		Member member = findConstSupplierMember(
				checkNotNull(clazz,"clazz is null"),
				checkNotNull(memberFilters,"memberFilters is null"), true);
		return readStaticValue(member);
	}
	@SafeVarargs
	public final <T> T readValue(Class<?> clazz, 
			Predicate<Member>... memberFilters) {
		return readValue(clazz,
				FluentIterable.from(checkNotNull(memberFilters,"memberFilters is null")));
	}
	public final <T> T readValue(T defaultValue,
			Class<?> clazz,
			Iterable<Predicate<Member>> memberFilters) {
		checkNotNull(memberFilters,"memberFilters is null");
		Member member = findConstSupplierMember(clazz, memberFilters,false);
		if(null == member) {
			return defaultValue;
		}
		T value = readStaticValue(member);
		return null == value ? defaultValue:value;
	}
	@SafeVarargs
	public final <T> T readValue(T defaultValue,
			Class<?> clazz,
			Predicate<Member>... memberFilters) {
		return readValue(defaultValue,clazz,
				FluentIterable.from(checkNotNull(memberFilters,"memberFilters is null")));
	}

	public final <T> T readValueByEntry(Class<? extends Annotation> classTag, Class<? extends Annotation> memberTag, String key,Object entryValue) {
		return readValueByEntry(classTag,memberTag,key,entryValue,null,true);
	}
	public final <T> ILazyInitVariable<T> readValueByEntryLazy(final Class<? extends Annotation> classTag, final Class<? extends Annotation> memberTag, final String key,final Object entryValue) {
		return new VolatileReferenceVar<T>() {
			@Override
			protected T doGet() {
				return readValueByEntry(classTag,memberTag,key,entryValue);
			}
		};
	}
	public final <T> T readValueByEntry(Class<? extends Annotation> classTag, Class<? extends Annotation> memberTag,String key,Object entryValue,T defaultValue) {
		return readValueByEntry(classTag,memberTag,key,entryValue,defaultValue,false);
	}
	public final <T> ILazyInitVariable<T> readValueByEntryLazy(final Class<? extends Annotation> classTag, final Class<? extends Annotation> memberTag,final String key,final Object entryValue,final T defaultValue) {
		return new VolatileReferenceVar<T>() {
			@Override
			protected T doGet() {
				return readValueByEntry(classTag,memberTag,key,entryValue,defaultValue);
			}
		};
	}
	private final <T> T readValueByEntry(Class<? extends Annotation> classTag, Class<? extends Annotation> memberTag,String key,Object entryValue,T defaultValue,boolean required
			) {
		checkNotNull(classTag,"classTag is null");
		checkNotNull(memberTag,"memberTag is null");
		checkNotNull(key,"key is null");
		checkNotNull(entryValue,"entryValue is null");
		List<Predicate<Class<?>>> classFilters = Arrays.asList(CommonPredicates.hasAnnotationClassFilter(classTag));
		List<Predicate<Member>> memberFilters = Arrays.asList(CommonPredicates.hasAnnotationMemberFilter(memberTag));
		Set<Member> members = findConstSupplierMembers(classFilters, memberFilters);
		List<Predicate<Member>> entryFilters = Arrays.asList(CommonPredicates.containedEntryMemberFilter(memberTag, key,entryValue));
		Member member = findMember(members,entryFilters,required);
		if(required) {
			return readStaticValue(member);
		}else {
			return readValue(member,defaultValue);
		}
	}
	public final <T> T readAssociatedConstant(Object entryValue) {
		try {
			return readValueByEntry(ConstantComponent.class,ConstantSupplier.class,ASSOCIATED,entryValue);
		} catch (PackageScanException e) {
			throw new PackageScanException(
					logString("NOT FOUND VALUE with {}={},caused by {}",ASSOCIATED,entryValue,e.getMessage()),e);
		}
	}
	public final <T> ILazyInitVariable<T> readAssociatedConstantLazy(final Object entryValue) {
		return new VolatileReferenceVar<T>() {
			@Override
			protected T doGet() {
				return readAssociatedConstant(entryValue);
			}
		};
	}
	public final <T> T readAssociatedConstant(Object entryValue, T defaultValue) {
		return readValueByEntry(ConstantComponent.class,ConstantSupplier.class,ASSOCIATED,entryValue,defaultValue);
	}
	public final <T> ILazyInitVariable<T> readAssociatedConstantLazy(final Object entryValue, final T defaultValue) {
		return new VolatileReferenceVar<T>() {
			@Override
			protected T doGet() {
				return readAssociatedConstant(entryValue,defaultValue);
			}
		};
	}
	@SuppressWarnings("unchecked")
	public final <T> T getSimpleInstance(Class<T> clazz,boolean onlyOne, T defaultValue, Iterable< Predicate<Class<?>>>filters){
		checkNotNull(clazz,"clazz is null");
		Class<?> targetClass = getClass(onlyOne, 
				withSimpleIClassFilter(clazz, filters).toArray(new Predicate[0]));
		try {
			return null == targetClass ? defaultValue:(T)targetClass.getConstructor().newInstance();
		} catch (Exception e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}
	}
	public final <T> Set<Class<?>> getSimpleClasses(Class<T> clazz,Supplier<RangeFilter> finisher,Iterable< Predicate<Class<?>>>filters){
		return getClasses(finisher,withSimpleIClassFilter(clazz, filters));
	}
	@SafeVarargs
	public final <T> Set<Class<?>> getSimpleClasses(Class<T> clazz,Supplier<RangeFilter> finisher,Predicate<Class<?>>...filters){
		return getSimpleClasses(clazz,finisher,null==filters ? null : Arrays.asList(filters));
	}
	
	static class TypeHierarchyMatcher implements Function<Iterable<Class<?>>,LinkedHashSet<Class<?>>>{
		private final boolean subFirstly;
		private final Predicate<Class<?>> inputFilter;
		public TypeHierarchyMatcher(Class<?> topClass) {
			ScanConfig scanConfig= AnnotatedElementUtils.findMergedAnnotation(checkNotNull(topClass,"topClass is null"), ScanConfig.class);
			if(null != scanConfig) {
				subFirstly = scanConfig.subClassFirstly();
			}else {
				subFirstly = true;
			}
			inputFilter = Predicates.and(Predicates.notNull(),Predicates.subtypeOf(topClass));
		}
		@Override
		public LinkedHashSet<Class<?>> apply(Iterable<Class<?>> classes) {
			LinkedHashSet<Class<?>> result = new LinkedHashSet<>();
			if(null != classes) {
				for(Class<?> clazz : FluentIterable.from(classes).filter(inputFilter)) {
					Predicate<Class<?>> checkFilter = CommonPredicates.typeHierarchyFilter(!subFirstly, result);
					if(!checkFilter.apply(clazz)) {
						Predicate<Class<?>> removeFilter = CommonPredicates.typeHierarchyFilter(!subFirstly,clazz);
						Iterables.removeIf(result, removeFilter);
						result.add(clazz);
					}
				}
			}
			return result;
		}
		
	}
	static class TypeHierarchyArrayMatcher implements Function<Class<?>[], Class<?>[]>{
		private final TypeHierarchyMatcher matcher;
		public TypeHierarchyArrayMatcher(Class<?> topClass) {
			matcher = new TypeHierarchyMatcher(topClass);
		}

		@Override
		public Class<?>[] apply(Class<?>[] input) {
			if(null == input) {
				return matcher.apply(FluentIterable.from(input)).toArray(new Class<?>[0]);
			}
			return new Class<?>[0];
		}
		
	}
	static LinkedHashSet<Class<?>> typeHierarchyFilter(Class<?>topClass, Iterable<Class<?>> classes){
		return  new TypeHierarchyMatcher(topClass).apply(classes);
	}
	static Class<?>[] typeHierarchyFilter(Class<?>topClass, Class<?>[] classes){
		return  new TypeHierarchyArrayMatcher(topClass).apply(classes);
	}
	static Class<?> singletonOf(Class<?>topClass, Iterable<Class<?>> classes){
		LinkedHashSet<Class<?>> result = typeHierarchyFilter(topClass,classes);
		switch(result.size()) {
		case 0:
			return null;
		case 1:
			return result.iterator().next();
		default:
			throw new PackageScanException(
					String.format("MULTI sub type found for %s:%s",
							topClass,
							CommonFunctions.joinFun().apply(result)));
		}
	}
	static Class<?> singletonOf(Class<?>topClass, Class<?>... classes){
		return singletonOf(topClass, FluentIterable.from(checkNotNull(classes,"classes is null")));
	}
	
	private final <T> Class<?> getSimpleClassByEntry(Class<T> superClass,T defaultValue, Class<? extends Annotation> classTag, String key,Object entryValue){
		checkNotNull(classTag,"classTag is null");
		Predicate<Class<?>> filter;
		if( key != null) {
			filter = CommonPredicates.<Class<?>>containedEntryAnnotatedElementFilter(classTag, key, checkNotNull(entryValue,"entryValue is null"));
		}else {
			filter = CommonPredicates.<Class<?>>hasAnnotationFilter(classTag);
		}
		if(null != superClass) {
			Set<Class<?>> simpleClasses = getSimpleClasses(superClass,CountLimitStrategy.ANY, filter);
			return singletonOf(superClass,simpleClasses);
		}else {
			Set<Class<?>> simpleClasses = getSimpleClasses(superClass,CountLimitStrategy.MOST_ONE,filter);
			return simpleClasses.isEmpty()?null:simpleClasses.iterator().next();
		}
	}
	@SuppressWarnings("unchecked")
	private final <T> T getSimpleInstanceByEntry(Class<T> clazz,T defaultValue, Class<? extends Annotation> classTag, String key,Object entryValue){
		Class<?> singletonClass = getSimpleClassByEntry(clazz,defaultValue,classTag,key,entryValue);
		if(null != singletonClass) {
			T instance = (T) Singleton.weakSingletonOf(singletonClass);
			return Optional.fromNullable(instance).or(Optional.fromNullable(defaultValue)).orNull();
		}else {
			return null;
		}
	}
	public final <T> T getComponentAssociated(Class<T> clazz,Object entryValue,T defaultValue){
		return getSimpleInstanceByEntry(clazz,defaultValue,CasbanComponent.class,ASSOCIATED, entryValue);
	}
	public final <T> T getComponentAssociated(Class<T> clazz,Object entryValue){
		return ConditionChecks.checkNotNull(
				getSimpleInstanceByEntry(clazz,null,CasbanComponent.class,ASSOCIATED, entryValue),
				PackageScanException.class, 
				"NOT FOUND SIMPLE INSTANCE annotated by @%s and %s=%s  FOR %s",(Object)CasbanComponent.class.getSimpleName(), ASSOCIATED,entryValue,clazz.getName());
	}
	public final <T> T getComponent(Class<T> clazz){
		return ConditionChecks.checkNotNull(
				getSimpleInstanceByEntry(clazz,null,CasbanComponent.class,null, null),
				PackageScanException.class, 
				"NOT FOUND SIMPLE INSTANCE annotated by @%s FOR %s",CasbanComponent.class.getSimpleName(), clazz.getName());
	}
	public final <T> T getComponent(Class<T> clazz,T defaultValue){
		return getSimpleInstanceByEntry(clazz,defaultValue,CasbanComponent.class,null, null);
	}
	public final Set<Class<?>> getAnnotatedClasses(Class<? extends Annotation> classTag){
		checkNotNull(classTag,"classTag is null");
		return getClasses(CountLimitStrategy.ANY, 
					CommonPredicates.hasAnnotationClassFilter(classTag),
					CommonPredicates.publicClassFilter(), 
					CommonPredicates.noAbstractClassFilter());
	}
	@SuppressWarnings("unchecked")
	public final <T> Class<? extends T> getAnnotatedClass(Class<T> superClass,Class<? extends Annotation> classTag){
		checkNotNull(superClass,"superClass is null");
		checkNotNull(classTag,"classTag is null");
		Set<Class<?>> result = getAnnotatedClasses(classTag);
		return (Class<? extends T>) ConditionChecks.checkNotNull(
				singletonOf(superClass,result),
				PackageScanException.class, 
				"NOT FOUND simple class annotated by @%s FOR %s",classTag.getSimpleName(), superClass.getName());
	}
	@SuppressWarnings("unchecked")
	
	@AoWeakCacheable(maximumSize = 1000, expireAfterAccess = 60, expireAfterAccessTimeUnit = TimeUnit.SECONDS)
	private static <T> T readStaticValue(Member member) {
		try {
			/***
			 * 反射获取静态方法或成员的值
			 */
			if(member instanceof Field) {
				return (T) ((Field)member).get(null);
			}else if (member instanceof Method) {
				return (T) ((Method)member).invoke(null);
			}
			return null;
		} catch (Exception e) {
			Throwables.throwIfUnchecked(e);
			throw new RuntimeException(e);
		}		
	}
	@SuppressWarnings("unchecked")
	private static <T> T readValue(Member member,T defaultValue) {
		return (T) Optional.fromNullable(readStaticValue(member)).or(Optional.fromNullable(defaultValue)).orNull();
	}
	
}
